<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>防抖</title>
</head>

<body>
  <button id="btndebunce">点击防抖</button>
  <script>
    /*  实现一个find函数，并且find函数能够满足下列条件
   
       title数据类型为string|null
       userId为主键，数据类型为number
   
       // 原始数据
       const data = [
         {userId: 8, title: 'title1'},
         {userId: 11, title: 'other'},
         {userId: 15, title: null},
         {userId: 19, title: 'title2'}
       ];
   
       // 查找data中，符合条件的数据，并进行排序
       const result = find(data).where({
         "title": /\d$/
       }).orderBy('userId', 'desc');
   
       // 输出
       [{ userId: 19, title: 'title2'}, { userId: 8, title: 'title1' }];
   */

    function find(origin) {
      return {
        data: origin,
        where: function (searchObj) {
          const key = Reflect.ownKeys(searchObj);
          console.log(key);
          for (let index = 0; index < key.length; index++) {
            this.data = this.data.filter(item => searchObj[key[index]].test(item[key[index]]));

          }
          return find(this.data);
        },
        orderBy: function (key, sorter) {
          this.data.sort((a, b) => {
            return sorter == 'desc' ? b[key] - a[key] : a[key] - b[key];
          });
          return this.data;
        }
      }
    }
    const data = [
      { userId: 8, title: 'title1' },
      { userId: 11, title: 'other' },
      { userId: 15, title: null },
      { userId: 19, title: 'title2' }
    ];

    const result = find(data).where({
      "title": /\d$/
    }).orderBy('userId', 'desc');
    console.log(result);

    /*
    对象的深度比较
  
  // 已知有两个对象obj1和obj2，实现isEqual函数判断对象是否相等
  const obj1 = {
    a: 1,
    c: 3,
    b: {
      c: [1, 2]
    }
  }
  const obj2 = {
    c: 4,
    b: {
      c: [1, 2]
    },
    a: 1
  }
  
  // isEqual函数，相等输出true，不相等输出false
  isEqual(obj1, obj2)
  
    */

    function isEqual(a, b) {
      const keyA = Object.keys(a);
      const keyB = Object.keys(b);

      if (keyA.length != keyB.length) return false;

      for (let index = 0; index < keyA.length; index++) {
        const key = keyA[index];
        // console.log(typeof a[key]);
        // 判断 当前key 对应的数据类型是否一致
        if (typeof a[key] != typeof b[key]) return false;

        // 判断 当前key如果不是对象类型，直接判断其值是否一样
        console.log("a:" + a[key] + ", b:" + b[key]);
        if (typeof a[key] !== 'object'
          && typeof b[key] !== 'object'
          && a[key] !== b[key]) return false;

        if (Array.isArray(a[key]) && Array.isArray(a[key])) {
          if (!arrayEqual(a[key], a[key])) return false;
        }
        // 递归判断
        if (typeof a[key] === 'object' && typeof b[key] === 'object') {
          if (!isEqual(a[key], b[key])) return false
        }
      }
      return true;
    }
    function arrayEqual(arr1, arr2) {
      if (arr1.length !== arr2.length) return false

      for (let i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) return false
      }

      return true
    }

    const obj1 = {
      a: 1,
      c: 3,
      b: {
        c: [1, 2]
      }
    }
    const obj2 = {
      c: 4,
      b: {
        c: [1, 2]
      },
      a: 1
    }
    var res = isEqual(obj1, obj2)
    // console.log(res);

    /*
    // 判断JS对象是否存在循环引用
    const obj = {
    a: 1,
    b: 2,
    }

    obj.c = obj

    // isHasCircle函数， 存在环输出true，不存在的话输出false
    isHasCircle(obj)
    */

    function isHasCircle(obj) {
      let hasCircle = false;
      const map = new Map();
      loop(obj);

      // 递归判断是否存在环
      function loop(obj) {
        const keys = Object.keys(obj);

        keys.forEach(key => {
          const value = obj[key];
          if (typeof value == 'object' && value !== null) {
            if (map.has(value)) {
              hasCircle = true;
              return;
            } else {
              map.set(value);
              loop(value);
            }
          }
        })
      }

      return hasCircle;
    }
  </script>
</body>

</html>